package http

import (
	"net/http"

	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/xuri/excelize/v2"
)

type Response struct {
	Status  bool        `json:"status"  example:"true"`    // 请求状态，为真时表示成功，此时code无意义
	Code    int         `json:"code"    example:"0"`       // 状态码，成功为0
	Message string      `json:"message" example:"success"` // 提示消息，一般为请求失败时的提示消息
	Data    interface{} `json:"data"`                      // 数据
}

// ResponseData 数据格式，用来辅助生成swagger文档
type ResponseData struct{}

// ResSuccess 输出成功信息
func ResSuccess(r *ghttp.Request, data interface{}, messages ...string) {
	ResJsonExit(r, true, data, 0, messages...)
}

// ResError 输出错误信息
func ResError(r *ghttp.Request, err error, codes ...int) {
	code := http.StatusBadRequest
	if len(codes) > 0 {
		code = codes[0]
	}
	ResJsonExit(r, false, g.Slice{}, code, err.Error())
}

// ResJson 发送json数据，不退出
func ResJson(r *ghttp.Request, status bool, data interface{}, code int, messages ...string) {
	message := ``
	if len(messages) > 0 {
		message = messages[0]
	}

	if data == nil {
		data = g.Slice{}
	}
	res, err := gjson.Encode(Response{
		Status:  status,
		Code:    code,
		Message: message,
		Data:    data,
	})

	r.Response.Header().Set("Content-Type", "application/json")
	if err == nil {
		r.Response.Write(res)
	} else {
		r.Response.Write(Response{
			Status:  false,
			Code:    http.StatusInternalServerError,
			Message: err.Error(),
			Data:    nil,
		})
	}
}

// ResJsonExit 发送json数据，退出
func ResJsonExit(r *ghttp.Request, status bool, data interface{}, code int, messages ...string) {
	ResJson(r, status, data, code, messages...)
	r.Exit()
}

// ExportExcel 导出excel报表
func ExportExcel(r *ghttp.Request, fileName string, header []interface{}, data [][]interface{}) {
	file := excelize.NewFile()
	streamWriter, err := file.NewStreamWriter("Sheet1")
	if err != nil {
		ResError(r, err)
	}

	if err = streamWriter.SetRow("A1", header); err != nil {
		ResError(r, err)
	}

	for k, row := range data {
		cell, _ := excelize.CoordinatesToCellName(1, k+2)
		_ = streamWriter.SetRow(cell, row)

	}

	if err = streamWriter.Flush(); err != nil {
		ResError(r, err)
	}

	r.Response.Header().Set(`Content-Disposition`, `attachment; filename=`+fileName+`.xlsx`)
	r.Response.Header().Set(`Content-Type`, `application/vnd.ms-excel; name='excel'`)
	_ = file.Write(r.Response.Writer)
	r.Exit()
}
